//package com.bestcem.xm.txtanls.job;
//
//
//import com.bestcem.xm.common.core.constant.Constants;
//import com.bestcem.xm.common.core.domain.web.ServiceResult;
//import com.bestcem.xm.componet.redis.service.RedisService;
//import com.bestcem.xm.txtanls.dao.AnalysisProjectDao;
//import com.bestcem.xm.txtanls.entity.pojo.ProjectDO;
//import com.bestcem.xm.txtanls.enums.AnalysisStatusEnum;
//import com.bestcem.xm.txtanls.enums.TrainStatusEnum;
//import com.bestcem.xm.txtanls.job.config.TrainJobConfig;
//import com.bestcem.xm.txtanls.service.AsyncTaskService;
//import com.bestcem.xm.txtanls.util.AnalysisUtil;
//import lombok.extern.slf4j.Slf4j;
//import org.quartz.Job;
//import org.quartz.JobExecutionContext;
//import org.redisson.api.RLock;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
//import org.springframework.stereotype.Component;
//import org.springframework.util.CollectionUtils;
//import org.springframework.util.ObjectUtils;
//
//import javax.annotation.Resource;
//import java.util.List;
//import java.util.Objects;
//import java.util.concurrent.TimeUnit;
//
///**
// * 增量训练
// *
// * @author XiaoYunSong <ys.xiao@idiaoyan.cn>
// * @version v1.0
// * @date 2021/5/21 15:43
// */
//@Slf4j
//@Component
//@ConditionalOnBean(TrainJobConfig.class)
//public class InactiveTrainingJob implements Job {
//    private static final Logger EMAIL_LOG = LoggerFactory.getLogger("EmailErrorLog");
//
//    @Resource
//    private AnalysisProjectDao analysisProjectDao;
//    @Resource
//    private AsyncTaskService asyncTaskService;
//    @Resource
//    private AnalysisUtil analysisUtil;
//    @Resource
//    private TrainJobConfig trainJobConfig;
//    @Resource
//    private RedisService redisService;
//
//    @Override
//    public void execute(JobExecutionContext jobExecutionContext) {
//        if (log.isInfoEnabled()) {
//            log.info("[Txtanls] 增量训练定时任务开始");
//        }
//        String jobName = jobExecutionContext.getJobDetail().getKey().getName();
//
//        // 查询所有的增量训练的项目
//        List<ProjectDO> projectList = analysisProjectDao.findAllByStatus(AnalysisStatusEnum.INACTIVE.getIndex());
//        if (CollectionUtils.isEmpty(projectList)) {
//            if (log.isInfoEnabled()) {
//                log.info("[Txtanls] 增量训练定时任务无满足目标");
//            }
//            return;
//        }
//        if (log.isInfoEnabled()) {
//            log.info("[Txtanls] 增量训练定时任务共 {} 条数据", projectList.size());
//        }
//
//        for (ProjectDO project : projectList) {
//            String projectId = project.getId();
//            // 获取锁
//            RLock lock = redisService.getLock(trainJobConfig.getTrainingJobLockKey(projectId));
//            if (lock.isLocked()) {
//                if (log.isInfoEnabled()) {
//                    log.info("[Txtanls] {} 项目已在增量训练", projectId);
//                }
//                return;
//            }
//
//            boolean isLocked = false;
//            try {
//                // 加锁, 不自动释放
//                if (lock.tryLock(0L, TimeUnit.SECONDS)) {
//                    isLocked = true;
//                    // 训练
//                    ServiceResult<Object> serviceResult = asyncTaskService.trainTask(project);
//                    if (!serviceResult.isSuccess()) {
//                        ErrorHandler(projectId, jobName, serviceResult.getMsg(), null);
//                    }
//                } else { // 加锁失败
//                    if (log.isInfoEnabled()) {
//                        log.info("[Txtanls] {} 项目已在增量训练", projectId);
//                    }
//                }
//            } catch (InterruptedException e) {
//                log.warn("[Txtanls] {} 项目增量训练获取锁被中断", projectId);
//            } catch (Exception e) {
//                if (!ObjectUtils.isEmpty(projectId)) {
//                    ErrorHandler(projectId, jobName, e.getMessage(), e);
//                }
//            } finally {
//                if (isLocked) {
//                    // 是否当前线程持有锁
//                    if (lock.isHeldByCurrentThread()) {
//                        // 手动释放锁
//                        lock.unlock();
//                    } else {
//                        log.error("[Txtanls] {} 项目增量训练锁持有对象转移", projectId);
//                    }
//                }
//            }
//        }
//
//        if (log.isInfoEnabled()) {
//            log.info("[Txtanls] 增量训练定时任务全部完成;");
//        }
//    }
//
//    /**
//     * 训练任务失败处理
//     *
//     * @param projectId 项目id
//     * @param jobName   任务名
//     * @param errorMsg  错误信息
//     * @author XiaoYunSong <ys.xiao@idiaoyan.cn>
//     * @date 2021/7/5 11:17
//     */
//    private void ErrorHandler(String projectId, String jobName, String errorMsg, Exception e) {
//        // 更新项目状态
//        int failedUpdateResult = analysisUtil.updateProjectStatus(projectId, AnalysisStatusEnum.INACTIVE);
//        if (failedUpdateResult == 0) {
//            log.error("[Txtanls] {} 失败任务更新项目状态失败", projectId);
//        }
//        // 更新训练状态
//        int updateStateEndResult = analysisProjectDao.updateAnalysisProjectProgress(projectId, TrainStatusEnum.FINISHED, Constants.PROGRESS_FINISHED);
//        if (updateStateEndResult == 0) {
//            log.error("[Txtanls] {} 失败任务更新训练状态失败", projectId);
//        }
//        if (Objects.isNull(e)) {
//            log.error("[Txtanls] {}-{} 增量训练失败; ErrorMsg: {}", jobName, projectId, errorMsg);
//            EMAIL_LOG.error("[Txtanls] {}-{} 增量训练失败; ErrorMsg: {}", jobName, projectId, errorMsg);
//        } else {
//            log.error("[Txtanls] {}-{} 增量训练失败; ErrorMsg: {}", jobName, projectId, errorMsg, e);
//            EMAIL_LOG.error("[Txtanls] {}-{} 增量训练失败; ErrorMsg: {}", jobName, projectId, errorMsg, e);
//        }
//    }
//}
